package desktop.agent;
 
import java.net.InetAddress;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBElement;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import javax.xml.ws.Endpoint;

import org.oasis_open.docs.wsrf._2004._06.wsrf_ws_resourceproperties_1_2_draft_01.QueryExpressionType;
import org.xmlsoap.schemas.ws._2003._03.addressing.AttributedURI;
import org.xmlsoap.schemas.ws._2003._03.addressing.EndpointReferenceType;
import org.xmlsoap.schemas.ws._2003._03.addressing.ServiceNameType;

import com.nortel.soa.oi.cct.basenotification.AgentPropertyListenerType;
import com.nortel.soa.oi.cct.basenotification.NotificationTopicType;
import com.nortel.soa.oi.cct.basenotification.TerminalConnectionStateListenerType;
import com.nortel.soa.oi.cct.basenotification.TopicExpressionType;
import com.nortel.soa.oi.cct.notification.SubscriptionPolicyType;
import com.nortel.soa.oi.cct.notificationproducer.NotificationProducer;
import com.nortel.soa.oi.cct.notificationproducer.SOAOICCTNotificationProducer;
import com.nortel.soa.oi.cct.types.AgentProperty;
import com.nortel.soa.oi.cct.types.SsoToken;
import com.nortel.soa.oi.cct.types.Terminal;
import com.nortel.soa.oi.cct.types.TerminalConnectionState;

public class SubscribeUtil {

	private static String port = "9090";
	private static NotificationConsumerImpl notificationHandler;
	private static String notificationConsumerUri  = "http://" + getIpAddress() + ":" + port + "/SOAOICCT/services/NotificationConsumer";;
	private static NotificationProducer  notificationProducerService;
	private static String localIpAddress;




	/* 
	 * Gets a connection to the NotificationProducer service that allows the 
	 * user to register for notifications
	 */
	public static NotificationProducer getNotificationProducerService(String serverDetails) {

		try {
			String nplocation = "http://"+ serverDetails +  "/SOAOICCT/services/NotificationProducer?wsdl";
			URL url = new URL(nplocation);
			notificationProducerService = new SOAOICCTNotificationProducer(url).getNotificationProducer();        
		} catch (Exception e) {
			e.printStackTrace();
		}
		return notificationProducerService;
	}

	private static String getIpAddress() {

		if (localIpAddress == null) {
			try {
				InetAddress addr = InetAddress.getLocalHost();
				localIpAddress = addr.getHostAddress();
				System.out.println("IP Address : " + localIpAddress.toString());
			}
			catch (Exception e) {
				e.printStackTrace();
			}
		}

		return localIpAddress;
	}




	public static void publishNotificationConsumer(OICCADNotificationListener notificationListener, ServiceUtil serviceUtil) {

		String notificationConsumerUri  = "http://" + getIpAddress() + ":" + port + "/SOAOICCT/services/NotificationConsumer";;
		System.err.println("Registering Consumer Listener on[" + notificationConsumerUri + "]");
		notificationHandler = new NotificationConsumerImpl();
		notificationHandler.setServiceUtil(serviceUtil);
		notificationHandler.setNotificationListener(notificationListener);
		Endpoint.publish(notificationConsumerUri, notificationHandler);
	}


	public static void unsubscribe(SsoToken ssoToken,
			EndpointReferenceType subscriptionReference) {
		try {
			if (notificationProducerService != null)
				notificationProducerService.unsubscribe(subscriptionReference, ssoToken);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public static EndpointReferenceType subscribe(SsoToken ssoToken, String serverDetails) throws Exception {

		System.err.println("subscribe = ");


		getNotificationProducerService(serverDetails);

		//Setup the endpoint reference type object 
		//This object details the endpoint where notifications will be sent to
		EndpointReferenceType consumerReference = new EndpointReferenceType();
		AttributedURI value = new AttributedURI();
		value.setValue(notificationConsumerUri);

		QName name = new QName("http://www.nortel.com/soa/oi/cct/NotificationConsumer", "SOAOICCT_NotificationConsumer");   
		consumerReference.setAddress(value);
		consumerReference.setServiceName(new ServiceNameType());
		consumerReference.getServiceName().setPortName("NotificationConsumer");
		consumerReference.getServiceName().setValue(name);


		Boolean useNotify = true;
		QueryExpressionType precondition = null;
		QueryExpressionType selector = null;
		XMLGregorianCalendar initialTerminationTime = null;

		SubscriptionPolicyType subscriptionPolicy = new SubscriptionPolicyType();
		subscriptionPolicy.setSessionTerminationImminentNotificationsEnabled(true);
		subscriptionPolicy.setSessionTerminationNotificationsEnabled(true);
		subscriptionPolicy.setSubscriptionTerminationImminentNotificationsEnabled(true);
		subscriptionPolicy.setSubscriptionTerminationNotificationsEnabled(true);




		//Detail the types of notifications that you are going to subscribe for
		TopicExpressionType topicExp = new TopicExpressionType();
		topicExp.setDialect("Simple");
		NotificationTopicType notificationTopic = new NotificationTopicType();


		TerminalConnectionStateListenerType terminalConnectionStateListener = new TerminalConnectionStateListenerType();
		List<TerminalConnectionState> terminalConnectionStateListenerEvents = new ArrayList<TerminalConnectionState>();
		terminalConnectionStateListener.getTerminalConnectionStateEvent().addAll(terminalConnectionStateListenerEvents);
		List<Terminal> terminalConnectionStateListenerEntities = new ArrayList<Terminal>();
		terminalConnectionStateListener.getTerminalEntity().addAll(terminalConnectionStateListenerEntities);
		notificationTopic.setTerminalConnectionStateListener(terminalConnectionStateListener);


	
		notificationTopic = addWildCardAgentPropertyNotifications(notificationTopic);
	

		QName _TopicExpressionTypeNotificationTopic_QNAME = new QName("http://www.nortel.com/soa/oi/cct/BaseNotification", "NotificationTopic");
		JAXBElement<NotificationTopicType> notificationTopicType = new JAXBElement<NotificationTopicType>(_TopicExpressionTypeNotificationTopic_QNAME, NotificationTopicType.class, TopicExpressionType.class, notificationTopic);

		topicExp.getContent().add(notificationTopicType);


		//Call the subscribe service
		try {


			EndpointReferenceType subscriptionEndpoint = notificationProducerService.subscribe(
					consumerReference, 
					topicExp, 
					useNotify, 
					precondition, 
					selector, 
					subscriptionPolicy, 
					initialTerminationTime, 
					ssoToken);
			System.err.println("subscribe = "  + subscriptionEndpoint.getSubscriptionId());

			if (notificationHandler != null) {
				notificationHandler.setSubscriptionReference(subscriptionEndpoint);
			}

			return subscriptionEndpoint;
		}
		catch (Exception e ) {
			e.printStackTrace();
			throw e;
		}

	}

	private static NotificationTopicType addWildCardAgentPropertyNotifications(NotificationTopicType notificationTopic){ 
		List<AgentProperty> agentPropertyListenerProperties = new ArrayList<AgentProperty>();
		AgentPropertyListenerType agentPropertyListener = new AgentPropertyListenerType();
		agentPropertyListener.getAgentPropertyEvent().addAll(agentPropertyListenerProperties);    
		notificationTopic.setAgentPropertyListener(agentPropertyListener);
		return notificationTopic;

	}

	
//	private static NotificationTopicType addWildCardTerminalPropertyNotifications(NotificationTopicType notificationTopic) {
//
//		List<TerminalProperty> termialPropertyListenerProperties = new ArrayList<TerminalProperty>();
//		TerminalPropertyListenerType terminalPropertyListener = new TerminalPropertyListenerType();
//		terminalPropertyListener.getTerminalPropertyEvent().addAll(termialPropertyListenerProperties);    
//		notificationTopic.setTerminalPropertyListener(terminalPropertyListener);
//		return notificationTopic;
//
//	}


//		private static NotificationTopicType addWildCardAgentStateNotifications(NotificationTopicType notificationTopic){ 
//			List<AgentState> agentStateListenerProperties = new ArrayList<AgentState>();
//			AgentStateListenerType agentStateListener = new AgentStateListenerType();
//			agentStateListener.getState().addAll(agentStateListenerProperties);    
//			notificationTopic.setAgentStateListener(agentStateListener);
//			return notificationTopic;
//	
//		}




	//	private static NotificationTopicType addWildCardConnectionStateNotifications(NotificationTopicType notificationTopic){ 
	//        List<ConnectionState> connectionStateListenerProperties = new ArrayList<ConnectionState>();
	//        ConnectionStateListenerType connectionStateListener = WSBN_OBJ_FACTORY.createConnectionStateListenerType();
	//        connectionStateListener.getConnectionStateEvent().addAll(connectionStateListenerProperties);    
	//        notificationTopic.setConnectionStateListener(connectionStateListener);
	//        return notificationTopic;
	//        
	//    }

	//    private static NotificationTopicType addWildCardContactPropertyNotifications(NotificationTopicType notificationTopic){ 
	//        List<ContactProperty> contactPropertyListenerProperties = new ArrayList<ContactProperty>();
	//        ContactPropertyListenerType contactPropertyListener = WSBN_OBJ_FACTORY.createContactPropertyListenerType();
	//        contactPropertyListener.getContactPropertyEvent().addAll(contactPropertyListenerProperties);    
	//        notificationTopic.setContactPropertyListener(contactPropertyListener);
	//        return notificationTopic;
	//        
	//    }




	//    private static NotificationTopicType addWildCardTerminalStateNotifications(NotificationTopicType notificationTopic){ 
	//        TerminalStateListenerType terminalStateListener = WSBN_OBJ_FACTORY.createTerminalStateListenerType();
	//        notificationTopic.setTerminalStateListener(terminalStateListener);
	//        return notificationTopic;
	//        
	//    }

	//    private static NotificationTopicType addWildCardAddressStateNotifications(NotificationTopicType notificationTopic){ 
	//        AddressStateListenerType addressStateListener = WSBN_OBJ_FACTORY.createAddressStateListenerType();
	//        notificationTopic.setAddressStateListener(addressStateListener);
	//        return notificationTopic;
	//    }


	//    private static NotificationTopicType addWildCardAddressPropertyNotifications(NotificationTopicType notificationTopic) {
	//        
	//        List<AddressProperty> addressPropertyListenerProperties = new ArrayList<AddressProperty>();
	//        AddressPropertyListenerType addressPropertyListener = WSBN_OBJ_FACTORY.createAddressPropertyListenerType();
	//        addressPropertyListener.getAddressPropertyEvent().addAll(addressPropertyListenerProperties);    
	//        notificationTopic.setAddressPropertyListener(addressPropertyListener);
	//        return notificationTopic;   
	//    }







}
